
import { ref, onMounted, onBeforeUnmount, createVNode, render , h, provide } from 'vue';

 
import ToolsNode from './tools';  
import bindEvent from '../urtls/bindEvent';   
import {ItalicOutlined,FontColorsOutlined,CodeOutlined,BlockOutlined,AmazonOutlined,TableOutlined,EnterOutlined} from '@vicons/antd';
import { CodeSlashOutline,FlashlightOutline, ReorderFourSharp, ListSharp } from '@vicons/ionicons5';
import { Editor, EditorContent } from "@tiptap/vue-3";
import StarterKit from "@tiptap/starter-kit";
import Document from "@tiptap/extension-document";
import Paragraph from "@tiptap/extension-paragraph";
import Text from "@tiptap/extension-text";
import Heading from "@tiptap/extension-heading";
import CodeBlock from "@tiptap/extension-code-block"; // 代码块
import BulletList from '@tiptap/extension-bullet-list'; //有序列表
import ListItem from '@tiptap/extension-list-item';
import FontFamily from '@tiptap/extension-font-family'
// 代码高亮highlight.js
import TextStyle from '@tiptap/extension-text-style'
import { Color } from '@tiptap/extension-color'
import { lowlight } from 'lowlight/lib/core';
import Highlight from '@tiptap/extension-highlight'
import { CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight';
import css from 'highlight.js/lib/languages/css';
import js from 'highlight.js/lib/languages/javascript';
import ts from 'highlight.js/lib/languages/typescript';
import html from 'highlight.js/lib/languages/xml';
import TextAlign from '@tiptap/extension-text-align'
// 表格
import Table from '@tiptap/extension-table'
import TableCell from '@tiptap/extension-table-cell'
import TableHeader from '@tiptap/extension-table-header'
import TableRow from '@tiptap/extension-table-row'
import { computed } from 'vue';
import Eventbus from '../urtls/eventBus';
// 初始化渲染
export const EditorContents = EditorContent;
const hiddensArr = ['heightlight','left,center,right,justify','Inter','serif','monospace','cursive','fontfamily']
// 图表
const Tollsicon = {
      'bold':{
            name:'bold',
            icon:AmazonOutlined,
            title:'加粗',
            action: (editor) => editor.chain().focus().toggleBold().run(), 
      },
      'italic':{
        name:'italic',
          icon:ItalicOutlined ,
          title: '斜体',
          action: (editor) => editor.chain().focus().toggleItalic().run(), 
        },  
        'strike':{
          name:'strike',
          icon: FontColorsOutlined,
          title: '文本线',
          action: (editor) => editor.chain().focus().toggleStrike().run(), 
        },
        'code':{
          name:'code',
          icon:CodeSlashOutline,
          title: '代码块',
          action: (editor) => editor.chain().focus().toggleCode().run(), 
        },
        'codeBlock':{
          name:'codeBlock',
          icon:CodeOutlined,
          title: '代码',
          action: (editor) => editor.chain().focus().toggleCodeBlock().run(), 
        },
        'separator':{
          name:'separator',
          icon:EnterOutlined,
          title: '回车',
          action: (editor) => editor.chain().focus().setHorizontalRule().run()
        },
        'blockquote':{
          name:'blockquote',
          icon: BlockOutlined,
          title: '块引用',
          action: (editor) => editor.chain().focus().toggleBlockquote().run()
        },
        'bulletList':{
          name:'bulletList',
          icon: ReorderFourSharp,
          title: '无序列表',
          action: (editor) => editor.chain().focus().toggleBulletList().run()
        },
        'orderedList':{
          name:'orderedList',
          icon: ListSharp,
          title: '有序列表',
          action: (editor) => editor.chain().focus().toggleOrderedList().run()
        },
        'table':{
          name:'table',
          icon: TableOutlined,
          title: '表格',
          action: (editor) => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
        },
        // "heightlight":{
        //   name:'heightlight',
        //   icon: FlashlightOutline,
        //   title: '高亮',
        //   action: null,
        //   colors:['red','blue']
        // },   
        "textalgin":{
          name:['left','center','right'],
          icon: [],
          title: '两端对齐',
          action: null,
          colors: []
        }, 
        
        
         
}

// table事件
let TableArrTip = [
  {
  name:'前加一列',
  type:'asd',
  clickEvent:(editor)=> editor.chain().focus().addColumnBefore().run()
  },
  {
    name:'后加一列',
    type:'asd',
    clickEvent:(editor)=> editor.chain().focus().addColumnAfter().run()
  },
  {
    name:'前加一列',
    type:'asd',
    clickEvent:(editor)=> editor.chain().focus().addColumnBefore().run()
  },
  {
    name:'移除col',
    type:'asd',
    clickEvent:(editor)=> editor.chain().focus().deleteColumn().run()
  },
  {
    name:'前加一行',
    type:'asd',
    clickEvent:(editor)=> editor.chain().focus().addRowBefore().run()
  },
  {
    name:'后加一行',
    type:'asd',
    clickEvent:(editor)=> editor.chain().focus().addRowAfter().run()
  },
  {
    name:'移除行',
    type:'asd',
    clickEvent:(editor)=> editor.chain().focus().deleteRow().run()
  },
  {
    name:'移除当前表格',
    type:'asd',
    clickEvent:(editor)=> editor.chain().focus().deleteTable().run()
  }, 
  
  {
    name:'合并&取消',
    type:'asd',
    clickEvent:(editor)=> editor.chain().focus().mergeOrSplit().run()
  }

];
// uuid b  v  
const uuid = ()=>(((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); 
const CustomHeading = Heading.extend({  
  addAttributes() {  
    return {
      id: { 
        renderHTML: element => {
          let ss = 'ha'+uuid();  
            return {
              id:ss,
            }
        },
      }, 
    }
  },
}) 
interface OptionsType{ editor: any,toolsele:Element,editable: boolean,tools:Partial<{bold:Boolean
  italic:Boolean,
  strike:Boolean,
  code:Boolean,
  codeBlock:Boolean,
  highlight:Boolean,
  separator:Boolean,
  orderedList:Boolean, // 有序列表
  bulletList:Boolean, // 无序列表 
  paragraph:Boolean,// 段落
  blockquote:Boolean, // 快引用
  table:Boolean,
  heightlight:Boolean,
  textalgin:Boolean,
  fontfamily:Boolean

}>};

export let Toopbar = ref();
  

type RenderEditorType = (option:OptionsType)=>Editor;
export const RenderEditor:RenderEditorType = (option:OptionsType,cbs:any) => {
  let { editor, editable,content } = option; 
  const editorInstince = ref();
  let appendTo = ref<Element>();
   
  const initeditor = () => {
  
      editor.value = new Editor({
        content:content,  // 初始化数据
        extensions: [
          StarterKit,
          BulletList,
          ListItem,
          Document,
          Paragraph,
          Text,
          TextStyle,
          Color, 
          FontFamily,
       
          TextAlign.configure({
            types: ['heading', 'paragraph'],
          }),
          Highlight.configure({ multicolor: true }),
          Table.configure({
            resizable: true,
          }),
          TableRow,
          TableHeader,
          TableCell,
          FontFamily,
          CodeBlock.configure({  
            languageClassPrefix: 'language-',
          }),
          CodeBlockLowlight.configure({
            lowlight,
          }),
          CustomHeading.configure({
            levels: [1, 2, 3, 4, 5, 6],
            HTMLAttributes: {
              class: 'my-custom-heading',
            },
          }),
        ],
        autofocus: true,
        editable, // 不可编辑
        injectCSS: false,
        parseOptions: {
          preserveWhitespace: 'full',
        },
        onFocus({ editor, event }) { 
          tabletipFun().lisenterFun(); 
        },
        onTransaction({ editor, transaction }) {
          headAddid();
           
        },
        onBlur({ editor, event }) { 
           //失去焦点的时候进行导出 
        },
        onUpdate: ({ editor }) => {
          const htmls = editor.getHTML();
          // 编辑、发布文章触发回调
          cbs(htmls)
        
        },
      });  
    
    editorInstince.value=editor.value;
  }
  editorInstince.value = editor.value;
  
  // head格式化- 防抖优化
  const headAddid = ()=>{ 
       let lists = document.querySelectorAll('.my-custom-heading');
       let appedtos = document.querySelector('.headlist'); 
       let domArrs = [...appedtos?.childNodes];
       domArrs.forEach(item=>{  
          if(!item.innerText.length || item.innerText=='\n' || item.innerText==''){ 
            appedtos?.removeChild(item);
          }
       }) 
       if(appedtos){ 
        lists.forEach(item=>{  
         let cachehead = document.querySelector(`#${item.id}`) as any;
         let cachedoms = document.querySelector(`.${item.id+'-'+cachehead.nodeName}`) as any; 
         if( cachedoms){ 
             if(cachedoms.innerText !==cachehead.innerText){
                cachedoms.innerText =  cachehead.innerText;
             } 
         }else{
           let doms = document.createElement('li');
           doms.className=item.id+'-'+cachehead.nodeName;
           doms.innerText =  cachehead.innerText; 
           doms.setAttribute('data-set',`#${item.id}`);
          //  跳转
           doms.onclick = (e)=>{
               e.preventDefault();
               let todom = document.querySelector(e.target.dataset.set);
               if(todom.scrollIntoView){
                todom.scrollIntoView()
               }
               
           }
           appedtos?.appendChild(doms);
         }
            
        })
       
       }
      
      //  


  }
  
  // 创建BubbleMenu--这里必须借助事件总线
  const onCreateBubbleMenu = (e)=>{
    Eventbus.emit('onCreateBubbleMenu',editor.value);
  }
  // 卸载
  onBeforeUnmount(() => {
    editor.value.destroy();
    tabletipFun().removeFun();
  })
  // tabletip
  const tabletipFun = ()=>{
    let doms = new bindEvent(document.querySelector('.editor_content_dome'));
    let bodys = new bindEvent(document.body);
    // 创建列表工具栏 
    Toopbar.value.innerHTML = '';
    TableArrTip.map((item)=>{
      const divO = document.createElement('div');
      divO.setAttribute('class','Menuitem');
      divO.innerText = item.name;
      divO.onclick = ()=>item.clickEvent(editor.value)
      Toopbar.value.appendChild(divO)
    })
    // 区域事件监听
    const lisenterFun = ()=>{
      doms.addEvenetListener('contextmenu',(e)=>{
          let acts = computed(()=>{
            console.log('asd')
            return editor.value.isActive('table')
          }) 
          doms.preventDefault(e);
          let parent = null; 
          parent = e.target.parentNode; 
          let upName = parent.nodeName.toUpperCase();
          if(upName=='TH' || upName=='TD'){
              let {top,left,width,height} = parent.getBoundingClientRect();
              let fReact = doms.getTarget().getBoundingClientRect();  
              Object.assign(Toopbar.value.style ?? {},{
                  top:(top-fReact.top+(height/2))+'px',
                  left:(left-fReact.left+(width/2))+'px',
                  opacity:'1',
                  zIndex:'99'
              })
          }else{
              Object.assign(Toopbar.value.style ?? {},{
                  top:'0',
                  left:'0',
                  opacity:'0',
                  zIndex:'-99'
              })
          }
      })
      bodys.addEvenetListener('click',(e)=>{  
        Object.assign(Toopbar.value.style ?? {},{
            top:'0',
            left:'0',
            opacity:'0',
            zIndex:'-99'
        })
    })
    }
    const removeFun = ()=>{
      Object.assign(Toopbar.value.style ?? {},{
        top:'0',
        left:'0',
        opacity:'0',
        zIndex:'-99'
    })
    doms.removeEventListener('contextmenu',()=>{})
    bodys.removeEventListener('click',()=>{})
    }
    return {
         removeFun,
         lisenterFun
    }
  }
  
  // baseConfig
  // Codelight
  const onCodelight = () => {
    lowlight.registerLanguage('html', html)
    lowlight.registerLanguage('css', css)
    lowlight.registerLanguage('js', js)
    lowlight.registerLanguage('ts', ts)
  }
  // tools
  // 实现：将每个需要添加的节点动态添加到页面中，最后事件冒泡处理（事件委托）
  const createToolsNode = (type:String,iconComp,title:String,items:any) => {
   
    const container = document.createElement('div'); 
    const props = {
      type: type,
      dataSet: type,
      class:type,
      color:items.colors ?? [],
      title,
      id: type,
      icon: iconComp, 
      editor:editor.value
    } 
 
    //创建虚拟dom
    const vnode = createVNode(
      ToolsNode,
      props
    ) 
    render(vnode, container);
    // 添加到视图中
    appendTo.value?.appendChild(container.firstElementChild!)
  }
  // 创建Menu
  const Toolslists = (list) => {
        Object.keys(list).map((item)=>{
              if(list[item] && Tollsicon[item]){ 
                createToolsNode(Tollsicon[item].name,Tollsicon[item].icon,Tollsicon[item].title,Tollsicon[item])
              }
        })
  }
  // 编辑器控件添加监听时间
  const addlisenterEvent = (e)=>{
           let parent = e.target.parentNode; 
           let chilrens = [...appendTo.value?.childNodes];
           if(parent && parent.parentNode){ 
            while( parent.parentNode && parent.parentNode!=appendTo.value){ 
                  parent = parent.parentNode;  
            } 
           }
           if(chilrens.includes(parent)){ 
                   let type = parent.getAttribute('dataset');
                 
                   if(type && !hiddensArr.includes(type)){
                    Tollsicon[type].action(editor.value); 
                   }
                    
           }  
  }
  appendTo.value = option.toolsele.value as Element; 
  appendTo.value?.addEventListener('click',addlisenterEvent)
  initeditor();
  onCodelight(); 
  Toolslists({...option.tools}); 
  onCreateBubbleMenu(editor);
  return editor.value
}


// 添加状态
const toggleClass = (target:Element,isActive:Boolean)=>{ 
       if(!isActive){
            target.classList?.remove('is-active');
       }else{
            target.classList?.add('is-active');
       }     
}



